package com.scs.application.modules.fsd.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.modules.fsd.consts.FsdConst;
import com.scs.application.modules.fsd.dto.SaveFpTempDTO;
import com.scs.application.modules.fsd.dto.SaveUserDTO;
import com.scs.application.modules.fsd.entity.FsdFpTemplets;
import com.scs.application.modules.fsd.entity.FsdStation;
import com.scs.application.modules.fsd.entity.FsdUser;
import com.scs.application.modules.fsd.mapper.*;
import com.scs.application.modules.fsd.service.*;
import com.scs.application.modules.sys.entity.OnlineUser;
import com.scs.application.modules.sys.security.UserPrincipal;
import com.scs.application.modules.sys.service.OnlineUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FsdUserServiceImpl extends BaseServiceImpl<FsdUserMapper, FsdUser> implements FsdUserService {

    private static  final String PASSWORD_SALT="scs-tech";
    @Value("${res.real-path}")
    private String resPath;

    @Autowired
    private OnlineUserService onlineUserService;

    @Autowired
    private FsdRoleService roleService;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private ChestUserMapper chestUserMapper;
    @Autowired
    private UsersChestGroupMapper usersChestGroupMapper;
    @Autowired
    private GroupUserMapper groupUserMapper;
    @Autowired
    private ChestChestGroupMapper chestChestGroupMapper;
    @Autowired
    private GroupRoleMapper groupRoleMapper;
    @Autowired
    private FsdAuthService fsdAuthService;
    @Autowired
    private FpTempletsService fsdFpTempletsService;
    @Autowired
    private SPDService spdService;

    @Override
    public String encryptPassword(String plainPassword) {
        return new Sha256Hash(plainPassword, PASSWORD_SALT).toHex();
    }

    @Override
    public FsdUser findByCode(String jobNumber) {
        return this.getOne(
                Wrappers.<FsdUser>query().eq("job_number", jobNumber).eq("disabled",0).last("limit 1")
        );
    }

//    @Override
//    public User findByJobNumber(String jobNumber) {
//        return this.getOne(
//                Wrappers.<User>query().eq("job_number", jobNumber).last("limit 1")
//        );
//    }

    @Override
    public Map<String, Object> getUsers(String keyword, Integer currentPage,Integer pageSize) {
        Map<String, Object> map = new HashMap<>();
        map.put("count", this.count(Wrappers.<FsdUser>query().like("job_number", keyword).or().like("user_name", keyword).or().like("user_name_py", keyword)));
        map.put("rows", this.list(
                Wrappers.<FsdUser>query().like("job_number", keyword).or().like("user_name", keyword).or().like("user_name_py", keyword).last("limit " + (currentPage - 1) * pageSize + "," + pageSize).orderByDesc("id")
        ));
        return map;
    }

    @Override
    public IPage<HashMap<String, Object>> getUserList(Page page, Wrapper wrapper) {
        return baseMapper.getUserList(page, wrapper);
    }

    @Override
    public String login(String jobNumber, String plainPassword,String stationCode) {
        FsdUser user = this.findByCode(jobNumber);
        if (user == null) {
            throw new BusinessException("账号或密码错误");
        }
        if (!user.getPassword().equals(plainPassword)) {
            throw new BusinessException("账号或密码错误");
        }
        if (getStationRoleByUserId(user.getId()).stream().filter((FsdStation s) -> s.getStationCode().equals(stationCode)).collect(Collectors.toList()).size() == 0)
            throw new BusinessException("用户没有该站点的权限");
        String token = onlineUserService.applyToken(user.getJobNumber(), "1");
        fsdAuthService.saveAuth(stationCode, user.getId());
        return token;
    }

    @Override
    public String fingerLogin(String id, String stationCode) {
        FsdFpTemplets fpTemplets = fsdFpTempletsService.getOne(Wrappers.<FsdFpTemplets>query().eq("id",id).eq("re_collection",0).last("limit 1"));
        if(fpTemplets == null)
            throw new BusinessException("登录失败，指纹失效");
        if (getStationRoleByUserId(fpTemplets.getUserId()).stream().filter((FsdStation s) -> s.getStationCode().equals(stationCode)).collect(Collectors.toList()).size() == 0)
            throw new BusinessException("用户没有该站点的权限");
        FsdUser user = this.getOne(Wrappers.<FsdUser>query().eq("id",fpTemplets.getUserId()).eq("disabled",0).last("limit 1"));
        if (user == null)
            throw new BusinessException("该用户已被禁用");
        String token = onlineUserService.applyToken(user.getJobNumber(), "1");
        fsdAuthService.saveAuth(stationCode, user.getId());
        return token;
    }

    @Override
    public boolean synchronizeUsers() {
        List<FsdUser> users = spdService.getUsers();
        List<String> jobNumbers = this.list().stream().map(FsdUser::getJobNumber).collect(Collectors.toList());
        users = users.stream().filter((FsdUser u) -> !jobNumbers.contains(u.getJobNumber())).collect(Collectors.toList());
        if (saveBatch(users)) {
            Collection<FsdFpTemplets> fsdFpTemplets = new ArrayList<>();
            for (FsdUser user : users) {
                FsdFpTemplets fpTemplets = new FsdFpTemplets();
                fpTemplets.setUserId(user.getId());
                fpTemplets.setRemark("指纹1");
                fpTemplets.setDiscarded(false);
                fpTemplets.setVersion(1);
                fsdFpTemplets.add(fpTemplets);
            }
            fsdFpTempletsService.saveBatch(fsdFpTemplets);
        }
        return true;
    }

    @Override
    public List<Map<String, Object>> getUserAuthLogByStationCode(String stationCode) {
        return fsdAuthService.getUserAuthLogByStationCode(stationCode);
    }

    @Override
    public Map uploadPhoto(MultipartFile file, String userId) {
        String userSavePath = resPath + FsdConst.FSD_USER_IMAGE_SUBPATH;
        String userThumbnailSavePath = resPath + FsdConst.FSD_USER_IMAGE_THUMBNAIL_SUBPATH;
        String fileName = userId + "." + getFileType(file.getOriginalFilename());
        try {
            File dir = new File(userSavePath);
            if (!dir.exists()) { // 判断目录是否存在
                dir.mkdirs();  //多层目录需要调用mkdirs
            }
            BufferedOutputStream out = new BufferedOutputStream(
                    new FileOutputStream(new File(userSavePath + fileName)));
            out.write(file.getBytes());
            out.flush();
            out.close();
            ImageUtils.resize(userSavePath + fileName, userThumbnailSavePath + fileName,
                    FsdConst.FSD_USER_IMAGE_THUMBNAIL_WIDTH, 0, 0, 0);
        } catch (Exception ex) {
            throw new BusinessException(ex.getMessage());
        }
        // 返回原图，缩略图的链接
        String vPath = FsdConst.FSD_USER_IMAGE_VPATH + fileName;
        String vPathThumbnail = FsdConst.FSD_USER_IMAGE_THUMBNAIL_VPATH + fileName;
        this.update(Wrappers.<FsdUser>update()
                .set("photo_url", vPath)
                .set("thumbnail_image_url", vPathThumbnail)
                .eq("id", userId));
        Map map = new HashMap<String, String>();
        map.put("url", vPath);
        map.put("thumbnailUrl", vPathThumbnail);
        return map;
    }

    @Override
    public String cardLogin(String id, String stationCode) {
        FsdUser fsdUser = this.getOne(Wrappers.<FsdUser>query().eq("card_id",id).eq("disabled",0).last("limit 1"));
        if(fsdUser == null)
            throw new BusinessException("登录失败，卡号未绑定或用户已禁用。");
        if (getStationRoleByUserId(fsdUser.getId()).stream().filter((FsdStation s) -> s.getStationCode().equals(stationCode)).collect(Collectors.toList()).size() == 0)
            throw new BusinessException("用户没有该站点的权限");
        String token = onlineUserService.applyToken(fsdUser.getJobNumber(), "1");
        fsdAuthService.saveAuth(stationCode, fsdUser.getId());
        return token;
    }

    @Override
    public Boolean info(String token) {
//        String token = WebUtils.getAccessToken();
        OnlineUser userToken = onlineUserService.findByToken(token);
        if (userToken == null) {
            return false;
        }else
            return true;
    }

    @Override
    public Boolean createUser(SaveUserDTO para) {
        FsdUser user = new FsdUser();
        user.setUserName(para.getUserName());
        user.setUserNamePy(PinYinUtils.getAlpha(para.getUserName()));
        user.setPassword(para.getPassword());
        user.setJobNumber(para.getJobNumber());
        user.setJob(para.getJob());
        user.setCardId(para.getCardID());
        user.setRelateId(para.getRelateId());
        save(user);
        Collection<FsdFpTemplets> fsdFpTemplets = new ArrayList<>();
        for (int i=0;i<para.getFpNum();i++){
            FsdFpTemplets fpTemplets = new FsdFpTemplets();
            fpTemplets.setUserId(user.getId());
            fpTemplets.setRemark("指纹"+(i+1));
            fpTemplets.setDiscarded(false);
            fpTemplets.setVersion(1);
            fsdFpTemplets.add(fpTemplets);
        }
        fsdFpTempletsService.saveBatch(fsdFpTemplets);
        return true;
    }

    @Override
    public Boolean editUser(SaveUserDTO para) {
        FsdUser fsd_user = this.getById(para.getId());
        fsd_user.setUserName(para.getUserName());
        fsd_user.setUserNamePy(PinYinUtils.getAlpha(para.getUserName()));
        fsd_user.setJobNumber(para.getJobNumber());
        fsd_user.setCardId(para.getCardID());
        fsd_user.setPassword(para.getPassword());
        fsd_user.setJob(para.getJob());
        fsd_user.setDisabled(para.getDisabled());
        fsd_user.setRelateId(para.getRelateId());
        updateById(fsd_user);
        return true;
    }

    @Override
    public void logout(String stationCode) {
        UserPrincipal currentUser = UserUtils.currentUser();
        String token = WebUtils.getAccessToken();
        OnlineUser userToken = onlineUserService.findByToken(token);
        if (userToken == null) {
            return;
        }
        /**
         * 从缓存中移除
         */
        CacheUtils.remove(CacheUtils.AUTHENTICATION_CACHE, token);
        onlineUserService.removeById(userToken.getId());
        SecurityUtils.getSubject().logout();
        fsdAuthService.saveUnAuth(stationCode,currentUser.getId());
//        CacheUtils.remove(CacheUtils.INTELLIC_CONFIGURATION,"config");
    }

    @Override
    public void changePwd(String userId, String newPassword) {
        this.update(Wrappers.<FsdUser>update()
                .set("password", newPassword)
                .eq("id", userId));

        // 踢出所有在线用户
        List<OnlineUser> onlineUsers = onlineUserService.list(Wrappers.<OnlineUser>query().eq("user_code", this.getOne(Wrappers.<FsdUser>query().eq("id",userId)).getJobNumber()));
        for (OnlineUser onlineUser : onlineUsers) {
            CacheUtils.remove(CacheUtils.AUTHENTICATION_CACHE, onlineUser.getToken());
            onlineUserService.removeById(onlineUser.getId());
        }
    }

    @Override
    public  List<Object> getRelationByUser(String id) {
        List<Object> rel=new ArrayList<Object>();
        rel.add(userRoleMapper.getRolesByUserId(id));
        rel.add(chestUserMapper.getChestsAndStationsByUserId(id));
        List<Map<String,Object>> chestGroups=usersChestGroupMapper.getChestGroupsByUser(id);
        rel.add(chestGroups);
        List<Map<String,Object>> groups=groupUserMapper.getGroupByUserId(id);
        rel.add(groups);
        List<String> chestGroupGuids = new ArrayList<String>();
        List<String> groupIds = new ArrayList<String>();
        for(Map<String,Object> ucg:chestGroups){
            chestGroupGuids.add(ucg.get("chestGroupId").toString());
        }
        for(Map<String,Object> g:groups){
            groupIds.add(g.get("groupId").toString());
        }
        rel.add(chestChestGroupMapper.getChestsAndStationsInChestGroupIds(chestGroupGuids));
        rel.add(groupRoleMapper.getRolesByGroupIds(groupIds));
        return rel;
    }

    @Override
    public Object getFpTempByUser(String userId) {
        if (fsdFpTempletsService.list(Wrappers.<FsdFpTemplets>query().eq("user_id", userId)).size() == 0)
            createFpTemp(userId);
        return fsdFpTempletsService.list(Wrappers.<FsdFpTemplets>query().eq("user_id", userId));
    }

    @Override
    public boolean createFpTemp(String userId) {
        FsdFpTemplets fpTemplets = new FsdFpTemplets();
        fpTemplets.setUserId(userId);
        fpTemplets.setRemark("指纹"+(fsdFpTempletsService.count(Wrappers.<FsdFpTemplets>query().eq("user_id", userId))+1));
        fpTemplets.setDiscarded(false);
        fpTemplets.setVersion(1);
        fsdFpTempletsService.save(fpTemplets);
        return true;
    }

    @Override
    public boolean editFpTemp(List<SaveFpTempDTO> fpTempDTOS) {
        Collection<FsdFpTemplets> fsdFpTemplets = new ArrayList<>();
        for(SaveFpTempDTO fpTempDTO:fpTempDTOS){
            FsdFpTemplets fpTemplets = new FsdFpTemplets();
            fpTemplets.setId(fpTempDTO.getId());
            fpTemplets.setRemark(fpTempDTO.getRemark());
            fpTemplets.setReCollection(fpTempDTO.getReCollection());
            fpTemplets.setDiscarded(fpTempDTO.getDiscarded());
            fpTemplets.setVersion(fpTempDTO.getVersion()+1);
            fsdFpTemplets.add(fpTemplets);
        }
        fsdFpTempletsService.updateBatchById(fsdFpTemplets);
        return true;
    }

    @Override
    public List<Map<String, Object>> getFpTempByUserList(List<String> userIds) {
        return fsdFpTempletsService.listMaps( Wrappers.<FsdFpTemplets>query().in("user_id",userIds));
    }


    public List<FsdStation> getStationRoleByUserId(String userId){
        return baseMapper.getStationRoleByUserId(userId);
    }

    private String getFileType(String fileName) {
        Integer start = fileName.lastIndexOf(".");
        if (start > -1) {
            return fileName.substring(start + 1);
        } else {
            return "";
        }
    }
}
